package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"gb28181/gb28181"
	"gb28181/internal/config"
	"gb28181/internal/manager"
	"gb28181/internal/server"
	"gb28181/internal/svc"

	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/service"
	"github.com/zeromicro/go-zero/zrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

var (
	configFile = flag.String("f", "etc/gb28181.yaml", "the config file")
	protocol   = flag.String("protocol", "none", "国标服务协议类型: tcp, udp, both, none(仅启动RPC)")
	tcpPort    = flag.Int("tcp-port", 5060, "TCP服务端口")
	udpPort    = flag.Int("udp-port", 5060, "UDP服务端口")
)

func main() {
	flag.Parse()

	// 加载配置
	var c config.Config
	conf.MustLoad(*configFile, &c)

	// 初始化日志
	logx.MustSetup(c.Log)

	// 创建客户端管理器
	clientMgr := manager.NewClientManager()

	// 创建服务上下文
	ctx := svc.NewServiceContext(c, clientMgr)

	// 创建信号通道
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// 启动RPC服务
	go startRPCServer(&c, ctx)

	// 根据协议类型启动国标服务
	switch *protocol {
	case "tcp":
		startTCPServer(&c, clientMgr, sigChan)
	case "udp":
		startUDPServer(&c, clientMgr, sigChan)
	case "both":
		startBothServers(&c, clientMgr, sigChan)
	case "none":
		logx.Info("仅启动RPC服务，不启动国标服务")
		waitForSignal(sigChan, func() {
			logx.Info("RPC服务已关闭")
		})
	default:
		logx.Errorf("不支持的协议类型: %s", *protocol)
		os.Exit(1)
	}
}

// startRPCServer 启动RPC服务
func startRPCServer(c *config.Config, ctx *svc.ServiceContext) {
	s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
		gb28181.RegisterGb28181Server(grpcServer, server.NewGb28181Server(ctx))

		if c.Mode == service.DevMode || c.Mode == service.TestMode {
			reflection.Register(grpcServer)
		}
	})
	defer s.Stop()

	fmt.Printf("Starting RPC server at %s...\n", c.ListenOn)
	s.Start()
}

// startTCPServer 启动TCP服务
func startTCPServer(c *config.Config, clientMgr *manager.ClientManager, sigChan chan os.Signal) {
	tcpServer := server.NewGB28181TCPServer(c, clientMgr)

	go func() {
		if err := tcpServer.Start(*tcpPort); err != nil {
			logx.Errorf("TCP服务器启动失败: %v", err)
			os.Exit(1)
		}
	}()

	logx.Infof("GB28181 TCP服务器已启动，监听端口: %d", *tcpPort)
	waitForSignal(sigChan, func() {
		tcpServer.Stop()
		logx.Info("TCP服务已关闭")
	})
}

// startUDPServer 启动UDP服务
func startUDPServer(c *config.Config, clientMgr *manager.ClientManager, sigChan chan os.Signal) {
	udpServer := server.NewGB28181UDPServer(c, clientMgr)

	go func() {
		if err := udpServer.Start(*udpPort); err != nil {
			logx.Errorf("UDP服务器启动失败: %v", err)
			os.Exit(1)
		}
	}()

	logx.Infof("GB28181 UDP服务器已启动，监听端口: %d", *udpPort)
	waitForSignal(sigChan, func() {
		udpServer.Stop()
		logx.Info("UDP服务已关闭")
	})
}

// startBothServers 同时启动TCP和UDP服务
func startBothServers(c *config.Config, clientMgr *manager.ClientManager, sigChan chan os.Signal) {
	tcpServer := server.NewGB28181TCPServer(c, clientMgr)
	udpServer := server.NewGB28181UDPServer(c, clientMgr)

	// 启动TCP服务器
	go func() {
		if err := tcpServer.Start(*tcpPort); err != nil {
			logx.Errorf("TCP服务器启动失败: %v", err)
			os.Exit(1)
		}
	}()

	// 启动UDP服务器
	go func() {
		if err := udpServer.Start(*udpPort); err != nil {
			logx.Errorf("UDP服务器启动失败: %v", err)
			os.Exit(1)
		}
	}()

	logx.Infof("GB28181 TCP/UDP服务器已启动，TCP端口: %d, UDP端口: %d", *tcpPort, *udpPort)
	waitForSignal(sigChan, func() {
		tcpServer.Stop()
		udpServer.Stop()
		logx.Info("TCP和UDP服务已关闭")
	})
}

// waitForSignal 等待信号并执行清理函数
func waitForSignal(sigChan chan os.Signal, cleanup func()) {
	sig := <-sigChan
	logx.Infof("接收到信号: %v", sig)
	cleanup()
}
